import { BaseScraper, type ScrapingResult } from '../BaseScraper.js';
import type { DataSourceConfig, ScrapingStrategy } from '../types/ScraperConfig.js';
import { DataConverter, type TemplateData } from '../DataConverter.js';
import type { CheerioAPI } from 'cheerio';

/**
 * 通用模板抓取策略
 */
export class TemplateScrapingStrategy extends BaseScraper implements ScrapingStrategy {
  name = 'TemplateScrapingStrategy';

  constructor(private config: DataSourceConfig) {
    super(`${config.name}TemplateScraper`, config.baseUrl);
    this.rateLimitDelay = config.scraping.rateLimitDelay;
    this.maxRetries = config.scraping.retry.maxRetries;
    this.retryDelay = config.scraping.retry.retryDelay;
  }

  matches(config: DataSourceConfig): boolean {
    return config.type === 'templates';
  }

  async scrape(): Promise<ScrapingResult> {
    const startTime = Date.now();
    const result: ScrapingResult = {
      success: false,
      count: 0,
      data: [],
      errors: [],
      timestamp: new Date(),
      duration: 0,
    };

    try {
      this.log(`🚀 开始抓取 ${this.config.name} 模板数据...`);
      
      // 获取模板列表
      const templateUrls = await this.getTemplateUrls();
      const totalTemplates = templateUrls.length;
      
      this.emitProgress({
        stage: '获取模板列表',
        current: 0,
        total: 100,
        message: `发现 ${totalTemplates} 个模板`,
      });

      const templates: TemplateData[] = [];

      // 抓取每个模板的详细信息
      for (let i = 0; i < templateUrls.length; i++) {
        const templateUrl = templateUrls[i];
        if (!templateUrl) continue;
        
        this.emitProgress({
          stage: '抓取模板详情',
          current: i + 1,
          total: templateUrls.length,
          item: templateUrl.name,
          message: `正在抓取 ${templateUrl.name}...`,
        });

        try {
          const templateData = await this.scrapeTemplate(templateUrl);
          if (templateData) {
            templates.push(templateData);
            this.log(`✅ 成功抓取: ${templateData.name}`);
          }
        } catch (error) {
          const errorMsg = `抓取模板 ${templateUrl.name} 失败: ${error instanceof Error ? error.message : String(error)}`;
          result.errors.push(errorMsg);
          this.error(errorMsg);
        }

        // 遵守速率限制
        await this.delay(this.rateLimitDelay);
      }

      result.data = templates;
      result.count = templates.length;
      result.success = true;
      
      this.log(`🎉 抓取完成! 成功收集 ${templates.length} 个模板`);

    } catch (error) {
      const errorMsg = `抓取过程发生错误: ${error instanceof Error ? error.message : String(error)}`;
      result.errors.push(errorMsg);
      this.error(errorMsg);
    }

    result.duration = Date.now() - startTime;
    return result;
  }

  /**
   * 获取模板URL列表
   */
  private async getTemplateUrls(): Promise<Array<{ name: string; url: string; category: string }>> {
    const templateUrls: Array<{ name: string; url: string; category: string }> = [];

    try {
      const listConfig = this.config.scraping.listPage;
      const paths = [listConfig.path, ...(listConfig.fallbackPaths || [])];

      for (const path of paths) {
        try {
          const html = await this.fetchPage(path);
          const $ = this.parseHtml(html);

          // 查找模板链接
          $(listConfig.itemSelector).each((_, element) => {
            const $item = $(element);
            const $link = $item.find(listConfig.linkSelector).first();
            const href = $link.attr('href');
            const name = this.extractName($, $item, listConfig.nameSelector);
            const category = this.extractCategory($, $item, listConfig.categorySelector);
            
            if (href && name) {
              templateUrls.push({
                name: this.normalizeTemplateName(name),
                url: this.normalizeUrl(href),
                category: this.normalizeCategory(category)
              });
            }
          });

          if (templateUrls.length > 0) {
            this.log(`📋 从 ${path} 发现 ${templateUrls.length} 个模板`);
            break;
          }
        } catch (error) {
          this.warn(`从 ${path} 抓取列表失败: ${error instanceof Error ? error.message : String(error)}`);
        }
      }

      // 如果没有找到，使用预定义模板列表
      if (templateUrls.length === 0) {
        const predefinedTemplates = this.getPredefinedTemplates();
        templateUrls.push(...predefinedTemplates);
        this.log(`📋 使用预定义模板列表，发现 ${templateUrls.length} 个模板`);
      }

      return this.deduplicateUrls(templateUrls);

    } catch (error) {
      this.error(`获取模板URL列表失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }

  /**
   * 抓取单个模板的详细信息
   */
  private async scrapeTemplate(templateInfo: { name: string; url: string; category: string }): Promise<TemplateData | null> {
    try {
      const html = await this.fetchPage(templateInfo.url);
      const $ = this.parseHtml(html);

      // 提取模板基本信息
      const title = this.extractTitle($) || templateInfo.name;
      const description = this.extractDescription($, templateInfo.name) || this.getDefaultDescription(templateInfo.name);
      const code = this.extractCode($) || this.generateDefaultCode(templateInfo.name);
      const dependencies = this.extractDependencies($, code);

      const templateData: TemplateData = {
        name: templateInfo.name,
        title: title,
        category: templateInfo.category,
        description: description,
        code: code,
        framework: 'react', // 默认React，可以根据配置调整
        dependencies: dependencies,
        preview_url: templateInfo.url,
        documentation_url: this.normalizeUrl(templateInfo.url),
        tags: this.generateTags(templateInfo),
        complexity: this.determineComplexity(code)
      };

      // 验证并修复数据完整性
      const validation = DataConverter.validateAndFixTemplate(templateData);
      if (!validation.valid) {
        this.error(`模板 ${templateInfo.name} 数据无效: ${validation.errors.join(', ')}`);
        return null;
      }

      return validation.fixedData;

    } catch (error) {
      this.error(`抓取模板 ${templateInfo.name} 失败: ${error instanceof Error ? error.message : String(error)}`);
      return null;
    }
  }

  /**
   * 提取名称
   */
  private extractName($: CheerioAPI, $item: any, selector: string): string {
    const name = $item.find(selector).first().text() || $item.text();
    return this.cleanText(name);
  }

  /**
   * 提取分类
   */
  private extractCategory($: CheerioAPI, $item: any, selector?: string): string {
    if (!selector) return '';
    const category = $item.find(selector).first().text();
    return this.cleanText(category);
  }

  /**
   * 提取标题
   */
  private extractTitle($: CheerioAPI): string {
    const selectors = this.config.scraping.detailPage.titleSelectors;
    
    for (const selector of selectors) {
      const title = $(selector).first().text();
      if (title) {
        const cleanTitle = this.cleanText(title);
        if (cleanTitle) {
          return cleanTitle;
        }
      }
    }

    return '';
  }

  /**
   * 提取描述
   */
  private extractDescription($: CheerioAPI, templateName: string): string {
    const selectors = this.config.scraping.detailPage.descriptionSelectors;

    for (const selector of selectors) {
      const desc = $(selector).text();
      if (desc && desc.length > 10) {
        return this.cleanText(desc);
      }
    }

    return '';
  }

  /**
   * 提取代码
   */
  private extractCode($: CheerioAPI): string {
    const selectors = this.config.scraping.detailPage.codeSelectors;

    for (const selector of selectors) {
      const code = $(selector).first().text();
      if (code && code.length > 50) {
        return DataConverter.formatCode(code);
      }
    }

    return '';
  }

  /**
   * 提取依赖
   */
  private extractDependencies($: CheerioAPI, code: string): string[] {
    const dependencies = new Set<string>();
    
    // 从代码中提取依赖
    if (code) {
      const codeDeps = DataConverter.extractDependencies(code);
      codeDeps.forEach(dep => dependencies.add(dep));
    }

    // 添加默认依赖
    const defaultDeps = this.getDefaultDependencies();
    defaultDeps.forEach(dep => dependencies.add(dep));

    return Array.from(dependencies);
  }

  /**
   * 获取默认依赖
   */
  private getDefaultDependencies(): string[] {
    const deps = ['react', 'antd'];
    
    if (this.config.id === 'ant-design-pro') {
      deps.push('@ant-design/pro-components');
    } else if (this.config.id === 'pro-components') {
      deps.push('@ant-design/pro-components');
    }

    return deps;
  }

  /**
   * 生成默认代码
   */
  private generateDefaultCode(templateName: string): string {
    return `import React from 'react';
import { ${templateName} } from '${this.config.processing.imports.defaultPath}';

const ${templateName}Template = () => {
  return (
    <${templateName} />
  );
};

export default ${templateName}Template;`;
  }

  /**
   * 确定复杂度
   */
  private determineComplexity(code: string): 'basic' | 'intermediate' | 'advanced' {
    if (!code) return 'basic';
    
    const lines = code.split('\n').length;
    const hasHooks = /use[A-Z]/.test(code);
    const hasComplexLogic = /useEffect|useCallback|useMemo/.test(code);
    
    if (lines > 100 || hasComplexLogic) return 'advanced';
    if (lines > 50 || hasHooks) return 'intermediate';
    return 'basic';
  }

  /**
   * 获取预定义模板列表
   */
  private getPredefinedTemplates(): Array<{ name: string; url: string; category: string }> {
    const templates = [
      { name: 'BasicLayout', url: '/layout/basic', category: '布局' },
      { name: 'ProLayout', url: '/layout/pro', category: '布局' },
      { name: 'LoginForm', url: '/form/login', category: '表单' },
      { name: 'TableList', url: '/table/list', category: '表格' },
      { name: 'Dashboard', url: '/dashboard/basic', category: '仪表板' }
    ];

    return templates.map(template => ({
      ...template,
      url: this.normalizeUrl(template.url)
    }));
  }

  /**
   * 获取默认描述
   */
  private getDefaultDescription(templateName: string): string {
    const defaultDesc = this.config.processing.defaultDescriptions[templateName];
    if (defaultDesc) return defaultDesc;
    
    // 根据模板名称生成描述
    const name = templateName.toLowerCase();
    if (name.includes('layout')) return `${templateName} - 页面布局模板`;
    if (name.includes('form')) return `${templateName} - 表单模板`;
    if (name.includes('table')) return `${templateName} - 表格模板`;
    if (name.includes('dashboard')) return `${templateName} - 仪表板模板`;
    
    return `${templateName} - ${this.config.name} 模板`;
  }

  /**
   * 生成标签
   */
  private generateTags(templateInfo: { name: string; category: string }): string[] {
    const tags = new Set<string>();
    
    // 添加基础标签
    tags.add('template');
    tags.add(this.config.type);
    if (templateInfo.category) {
      tags.add(templateInfo.category.toLowerCase());
    }

    // 根据规则生成标签
    for (const rule of this.config.processing.tagRules) {
      const target = rule.type === 'name' ? templateInfo.name : templateInfo.category;
      const pattern = typeof rule.pattern === 'string' ? new RegExp(rule.pattern, 'i') : rule.pattern;
      
      if (pattern.test(target)) {
        rule.tags.forEach(tag => tags.add(tag));
      }
    }

    return Array.from(tags);
  }

  /**
   * 规范化模板名称
   */
  private normalizeTemplateName(name: string): string {
    return name
      .replace(/^template-/, '')
      .replace(/-template$/, '')
      .trim();
  }

  /**
   * 规范化分类
   */
  private normalizeCategory(category: string): string {
    if (!category) return '其他';
    
    const mapping = this.config.processing.categoryMapping;
    return mapping[category] || category;
  }

  /**
   * 去重URL列表
   */
  private deduplicateUrls(urls: Array<{ name: string; url: string; category: string }>): Array<{ name: string; url: string; category: string }> {
    const seen = new Set<string>();
    return urls.filter(url => {
      const key = url.name.toLowerCase();
      if (seen.has(key)) return false;
      seen.add(key);
      return true;
    });
  }
}